﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace HeresyManager
{
    [Serializable]
    public abstract class Skill : HeresyManager.IPrecondition
    {
        public abstract String Name { get; }

        public SkillLevel Level { get; private set; }

        [ContractInvariantMethod]
        void Invariants()
        {
            Contract.Invariant(Name != null);
        }

        public Skill(SkillLevel level)
        {
            Level = level;
        }

        public virtual bool IsPreconditionSattisfied(Character c)
        {
            return this.Level == SkillLevel.Skilled ||
                this.Level == SkillLevel.Basic ||
                c.Skills.Any(
                    t => (this.GetType().IsAssignableFrom(t.Item1.GetType()) && t.Item1.Level == (this.Level - 1))
                    );

            //flase
            //typeof(String).IsAssignableFrom(typeof(Object))
            //true
            //typeof(Object).IsAssignableFrom(typeof(String))
        }

        public override string ToString()
        {
            return Name + (Level != SkillLevel.Skilled ? " " + Level.ToString() : "");
        }

        public static bool operator !=(Skill first, Skill second)
        {
            return !first.Equals(second);
        }
        public static bool operator ==(Skill first, Skill second)
        {
            if (first as object == null)
                return second as object == null;
            return first.Equals(second);
        }

        // override object.Equals
        public override bool Equals(object obj)
        {
            //       
            // See the full list of guidelines at
            //   http://go.microsoft.com/fwlink/?LinkID=85237  
            // and also the guidance for operator== at
            //   http://go.microsoft.com/fwlink/?LinkId=85238
            //

            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            var other = (Skill)obj;
            return Level == other.Level;
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            int prime = 31;
            int result = 1;
            result = prime
                    * result
                    + this.GetType().GetHashCode();
            result = prime
                    * result
                    + this.Level.GetHashCode();
            return result;
        }

        public enum SkillLevel
        {
            Basic = 0,
            Skilled = 1,
            Advanced = 2,
            Master = 3
        }

        internal virtual IEnumerator<Comunication.Comunicator> Accire(Character character)
        {
            if (false)
                yield return null;
        }
        internal virtual void DeAccire(Character character)
        {
        }
    }
}
